package com.heima.user.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.models.common.Result;
import com.heima.models.users.Users;
import com.heima.user.mapper.UsersMapper;
import com.heima.user.service.UsersService;
import com.heima.user.uitls.SendSms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @author itheima
 * @since 2023-07-03
 */
@Service
public class UsersServiceImpl implements UsersService {

    @Autowired
    private SendSms sendSms;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private UsersMapper usersMapper;

    @Override
    public String getCode(String phone) throws Exception {
        // 1. 判空
        if (StrUtil.isBlank(phone)) {
            return "fail";
        }

        // 2. 生成验证码
        Random random = new Random();
        int code = random.nextInt(9000) + 1000;

        // 补充1：发送短信之前，要判断上一次发送的验证是否还存在于redis
        String codeFromCache = redisTemplate.opsForValue().get(phone);
        if (StrUtil.isNotBlank(codeFromCache)) {
            return "短信发送过于频繁";
        }

        // 3. 发送验证码
        sendSms.send(phone, code + "");

        // 补充2：每次发完短信后，要记录一下今天发送了第几次短信
        // 在redis里面新增一个计数器，用来存储 我在今天发送短信的次数
        // increment 方法可以对指定的key值进行+1操作
        redisTemplate.opsForValue().increment("timer:" + phone);
        // 计数器，一天清除一次
        // 23:59 - 9:33 -> 毫秒数
        // 获取当前时间 LocalDateTime
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime target = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 23, 59, 59);
        Duration between = Duration.between(now, target);
        long time = between.getSeconds() * 1000;

        // 参数一：key
        // 参数二：过期时间
        // 参数三：过期时间单位
        redisTemplate.expire("timer:" + phone, time, TimeUnit.MICROSECONDS);

        // 当我想把验证码缓存到redis的时候，我需要判断一下，本次验证码生成是今天的第几次，如果超过3次，就变成60分钟
        String count = redisTemplate.opsForValue().get("timer:" + phone);

        // 4. 生成的验证码存储到Redis里面
        // key: 手机号
        // value: 验证码
        // 过期时间
        // 过期时间单位
        redisTemplate.opsForValue().set(phone, code + "", 60, Integer.parseInt(count) <= 3 ? TimeUnit.SECONDS : TimeUnit.MINUTES);

        return "ok";
    }

    @Override
    public Result getUsersByIdList(List<String> idList) {
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Users::getId, idList);
        return Result.success(usersMapper.selectList(wrapper));
    }
}
